$import( "SmitearWebGL.Programs.AbstractProgram" );

SmitearWebGL.Programs.Hdr.AdaptationProgram = SmitearWebGL.Programs.AbstractProgram.extend(
{
	/******** constructor ********/
	
	init : function()
	{
		this._super();
		this._registClass( "SmitearWebGL.Programs.Hdr.AdaptationProgram" );
	}
	,
	
	/******** public method ********/
	
	activeUniform : function( renderSession, renderableObject )
	{
		this.context.gl.uniform1f( this._shader.uniforms.uElapsedTime.location, renderSession.deltaTime * 2.0 );
		this.context.gl.uniformMatrix4fv( this._shader.uniforms.uDSOffsetsX.location, false, renderableObject._dsOffsetsX );
		this.context.gl.uniformMatrix4fv( this._shader.uniforms.uDSOffsetsY.location, false, renderableObject._dsOffsetsY );
		
		var texture = renderableObject.getTextureAt( 0 );
		this.context.gl.activeTexture( this.context.gl.TEXTURE0 );
		this.context.gl.bindTexture( this.context.gl.TEXTURE_2D, texture.getGlTexture() );
		this.context.gl.generateMipmap( this.context.gl.TEXTURE_2D );
		this.context.gl.uniform1i( this._shader.uniforms.uCurrentLum.location, 0 );
		
		texture = renderableObject.getTextureAt( 1 );
		this.context.gl.activeTexture( this.context.gl.TEXTURE1 );
		this.context.gl.bindTexture( this.context.gl.TEXTURE_2D, texture.getGlTexture() );
		this.context.gl.uniform1i( this._shader.uniforms.uAdaptedLum.location, 1 );
		
		return SmitearWebGL.Core.HResult.SUCCESS;
	}
	,
	
	/******** private method ********/
	
	_generateVertexShaderStr : function()
	{
		this._super();
		
		var vertStr =
		"\
		attribute vec3 " + SmitearWebGL.Resources.Buffer.AttribLocation.POSITION +";\n\
		varying vec2 vTexCoord;\n\
		void main(void)\n\
		{\n\
			vec4 pos = vec4(" + SmitearWebGL.Resources.Buffer.AttribLocation.POSITION +", 1.0);\n\
			gl_Position = pos;\n\
			vTexCoord = vec2((pos.x + 1.0) * 0.5, (pos.y + 1.0) * 0.5);\n\
		}\n\
		";
		
		return vertStr;
	}
	,
	_generateFragmentShaderStr : function()
	{
		this._super();
		
		var fragStr = "";
		
		if ( this.context.capacity.supported.OES_texture_float )
		{
			fragStr =
			"\
			#ifdef GL_ES\n\
			precision highp float;\n\
			#endif\n\
			varying vec2 vTexCoord;\n\
			uniform mat4 uDSOffsetsX;\n\
			uniform mat4 uDSOffsetsY;\n\
			uniform sampler2D uCurrentLum;\n\
			uniform sampler2D uAdaptedLum;\n\
			uniform float uElapsedTime;\n\
			void main(void) {\n\
				vec4 color = vec4( 0.0, 0.0, 0.0, 0.0 );\n\
				float maximum = -1e20;\n\
				float average = 0.0;\n\
				float dsOffsetsX[16];\n\
				dsOffsetsX[0] = uDSOffsetsX[0][0];\n\
				dsOffsetsX[1] = uDSOffsetsX[0][1];\n\
				dsOffsetsX[2] = uDSOffsetsX[0][2];\n\
				dsOffsetsX[3] = uDSOffsetsX[0][3];\n\
				dsOffsetsX[4] = uDSOffsetsX[1][0];\n\
				dsOffsetsX[5] = uDSOffsetsX[1][1];\n\
				dsOffsetsX[6] = uDSOffsetsX[1][2];\n\
				dsOffsetsX[7] = uDSOffsetsX[1][3];\n\
				dsOffsetsX[8] = uDSOffsetsX[2][0];\n\
				dsOffsetsX[9] = uDSOffsetsX[2][1];\n\
				dsOffsetsX[10] = uDSOffsetsX[2][2];\n\
				dsOffsetsX[11] = uDSOffsetsX[2][3];\n\
				dsOffsetsX[12] = uDSOffsetsX[3][0];\n\
				dsOffsetsX[13] = uDSOffsetsX[3][1];\n\
				dsOffsetsX[14] = uDSOffsetsX[3][2];\n\
				dsOffsetsX[15] = uDSOffsetsX[3][3];\n\
				float dsOffsetsY[16];\n\
				dsOffsetsY[0] = uDSOffsetsY[0][0];\n\
				dsOffsetsY[1] = uDSOffsetsY[0][1];\n\
				dsOffsetsY[2] = uDSOffsetsY[0][2];\n\
				dsOffsetsY[3] = uDSOffsetsY[0][3];\n\
				dsOffsetsY[4] = uDSOffsetsY[1][0];\n\
				dsOffsetsY[5] = uDSOffsetsY[1][1];\n\
				dsOffsetsY[6] = uDSOffsetsY[1][2];\n\
				dsOffsetsY[7] = uDSOffsetsY[1][3];\n\
				dsOffsetsY[8] = uDSOffsetsY[2][0];\n\
				dsOffsetsY[9] = uDSOffsetsY[2][1];\n\
				dsOffsetsY[10] = uDSOffsetsY[2][2];\n\
				dsOffsetsY[11] = uDSOffsetsY[2][3];\n\
				dsOffsetsY[12] = uDSOffsetsY[3][0];\n\
				dsOffsetsY[13] = uDSOffsetsY[3][1];\n\
				dsOffsetsY[14] = uDSOffsetsY[3][2];\n\
				dsOffsetsY[15] = uDSOffsetsY[3][3];\n\
				for( int i = 0; i < 16; i++ )\n\
				{\n\
					color = texture2D( uCurrentLum, vTexCoord + vec2( dsOffsetsX[i], dsOffsetsY[i] ) );\n\
					average += color.r;\n\
					maximum = max( maximum, color.g );\n\
				}\n\
				average /= 16.0;\n\
				vec4 adaptedMap = texture2D( uAdaptedLum, vTexCoord );\n\
				float adaptedLum = adaptedMap.r / adaptedMap.b;\n\
				float adaptedMax = adaptedMap.g / adaptedMap.a;\n\
				float sp = uElapsedTime / 300.0;\n\
				average = adaptedLum + (average - adaptedLum) * sp;\n\
				maximum = adaptedMax + (maximum - adaptedMax) * sp * 0.2;\n\
				gl_FragColor = vec4( average, maximum, 1.0, 1.0 );\n\
			}\n\
			";
		}
		else
		{
			fragStr =
			"\
			#ifdef GL_ES\n\
			precision highp float;\n\
			#endif\n\
			varying vec2 vTexCoord;\n\
			uniform mat4 uDSOffsetsX;\n\
			uniform mat4 uDSOffsetsY;\n\
			uniform sampler2D uCurrentLum;\n\
			uniform sampler2D uAdaptedLum;\n\
			uniform float uElapsedTime;\n\
			void main(void) {\n\
				vec4 color = vec4( 0.0, 0.0, 0.0, 0.0 );\n\
				float maximum = -1e20;\n\
				float average = 0.0;\n\
				float b = 1.0;\n\
				float a = 1.0;\n\
				float dsOffsetsX[16];\n\
				dsOffsetsX[0] = uDSOffsetsX[0][0];\n\
				dsOffsetsX[1] = uDSOffsetsX[0][1];\n\
				dsOffsetsX[2] = uDSOffsetsX[0][2];\n\
				dsOffsetsX[3] = uDSOffsetsX[0][3];\n\
				dsOffsetsX[4] = uDSOffsetsX[1][0];\n\
				dsOffsetsX[5] = uDSOffsetsX[1][1];\n\
				dsOffsetsX[6] = uDSOffsetsX[1][2];\n\
				dsOffsetsX[7] = uDSOffsetsX[1][3];\n\
				dsOffsetsX[8] = uDSOffsetsX[2][0];\n\
				dsOffsetsX[9] = uDSOffsetsX[2][1];\n\
				dsOffsetsX[10] = uDSOffsetsX[2][2];\n\
				dsOffsetsX[11] = uDSOffsetsX[2][3];\n\
				dsOffsetsX[12] = uDSOffsetsX[3][0];\n\
				dsOffsetsX[13] = uDSOffsetsX[3][1];\n\
				dsOffsetsX[14] = uDSOffsetsX[3][2];\n\
				dsOffsetsX[15] = uDSOffsetsX[3][3];\n\
				float dsOffsetsY[16];\n\
				dsOffsetsY[0] = uDSOffsetsY[0][0];\n\
				dsOffsetsY[1] = uDSOffsetsY[0][1];\n\
				dsOffsetsY[2] = uDSOffsetsY[0][2];\n\
				dsOffsetsY[3] = uDSOffsetsY[0][3];\n\
				dsOffsetsY[4] = uDSOffsetsY[1][0];\n\
				dsOffsetsY[5] = uDSOffsetsY[1][1];\n\
				dsOffsetsY[6] = uDSOffsetsY[1][2];\n\
				dsOffsetsY[7] = uDSOffsetsY[1][3];\n\
				dsOffsetsY[8] = uDSOffsetsY[2][0];\n\
				dsOffsetsY[9] = uDSOffsetsY[2][1];\n\
				dsOffsetsY[10] = uDSOffsetsY[2][2];\n\
				dsOffsetsY[11] = uDSOffsetsY[2][3];\n\
				dsOffsetsY[12] = uDSOffsetsY[3][0];\n\
				dsOffsetsY[13] = uDSOffsetsY[3][1];\n\
				dsOffsetsY[14] = uDSOffsetsY[3][2];\n\
				dsOffsetsY[15] = uDSOffsetsY[3][3];\n\
				for( int i = 0; i < 16; i++ )\n\
				{\n\
					color = texture2D( uCurrentLum, vTexCoord + vec2( dsOffsetsX[i], dsOffsetsY[i] ) );\n\
					color.r /= color.b;\n\
					color.g /= color.a;\n\
					average += color.r;\n\
					maximum = max( maximum, color.g );\n\
				}\n\
				average /= 16.0;\n\
				vec4 adaptedMap = texture2D( uAdaptedLum, vTexCoord );\n\
				float adaptedLum = adaptedMap.r / adaptedMap.b;\n\
				float adaptedMax = adaptedMap.g / adaptedMap.a;\n\
				float sp = uElapsedTime / 300.0;\n\
				average = adaptedLum + (average - adaptedLum) * sp;\n\
				maximum = adaptedMax + (maximum - adaptedMax) * sp * 0.2;\n\
				if ( average > 1.0 )\n\
				{\n\
					b = 1.0 / average;\n\
					average = 1.0; \n\
				}\n\
				if ( maximum > 1.0 )\n\
				{\n\
					a = 1.0 / maximum;\n\
					maximum = 1.0; \n\
				}\n\
				gl_FragColor = vec4( average, maximum, b, a );\n\
			}\n\
			";
		}
		
		return fragStr;
	}
}
);